package pl.edu.agh.uddiProxy;

import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;

import pl.edu.agh.uddiProxy.dao.DAOHelper;
import pl.edu.agh.uddiProxy.dao.DynamicParameterDAO;
import pl.edu.agh.uddiProxy.parameter.DownloadWSDLParameter;
import pl.edu.agh.uddiProxy.query.FindTModelQuery;
import pl.edu.agh.uddiProxy.types.ServiceDynamicParameters;
import pl.edu.agh.uddiProxy.types.TModel;
import dk.itst.uddi.client.query.FindBindingQuery;
import dk.itst.uddi.client.query.FindBindingResult;
import dk.itst.uddi.client.query.FindBusinessQuery;
import dk.itst.uddi.client.query.FindRelatedBusinessesQuery;
import dk.itst.uddi.client.query.FindServiceQuery;
import dk.itst.uddi.client.types.core.BindingTemplate;
import dk.itst.uddi.client.types.core.BusinessEntity;
import dk.itst.uddi.client.types.core.BusinessInfo;
import dk.itst.uddi.client.types.core.BusinessService;
import dk.itst.uddi.client.types.core.OperationalInfo;
import dk.itst.uddi.client.types.core.OverviewDoc;
import dk.itst.uddi.client.types.core.OverviewURL;
import dk.itst.uddi.client.types.core.ServiceInfo;
import dk.itst.uddi.client.types.core.TModelInfo;

public class InquiryClient implements InquiryClientInterface {
	private DynamicParameterDAO dynamicParameterDAO;
	private Map<String, String> authorizedNameMap = new WeakHashMap<String, String>();  

	public InquiryClient() {
		dynamicParameterDAO = DAOHelper.getDynamicParameterDAO();
	}
	
	public InquiryClient(UDDIClient client, DynamicParameterDAO dynamicParameterDAO) {
		this.dynamicParameterDAO = dynamicParameterDAO;
	}
	
	public FindBindingQuery findBinding() {
		return UDDIClient.getClient().getInquiry().findBinding();
	}
	
	public FindBusinessQuery findBusiness() {
		return UDDIClient.getClient().getInquiry().findBusiness();
	}
	
	public FindRelatedBusinessesQuery findRelatedBusinesses() {
		return UDDIClient.getClient().getInquiry().findRelatedBusinesses();
	}
	
	public FindServiceQuery findService() {
		return UDDIClient.getClient().getInquiry().findService();
	}
	
	public BindingTemplate getBinding(String key) {
		return UDDIClient.getClient().getInquiry().getBinding(key);
	}
	
	public BindingTemplate[] getBindings(String[] keys) {
		return UDDIClient.getClient().getInquiry().getBindings(keys);
	}
	
	public BusinessEntity[] getBusinessEntities(String[] keys) {
		return UDDIClient.getClient().getInquiry().getBusinessEntities(keys);
	}
	
	public BusinessEntity getBusinessEntity(String businessKey) {
		return UDDIClient.getClient().getInquiry().getBusinessEntity(businessKey);
	}
	
	public synchronized OperationalInfo getOperationalInfo(String entityKey) {
		return UDDIClient.getClient().getInquiry().getOperationalInfo(entityKey);
	}
	
	public synchronized String getAuthorizedName(String entityKey) {
		if (authorizedNameMap.containsKey(entityKey)) {
			return authorizedNameMap.get(entityKey);
		}
		String name = UDDIClient.getClient().getInquiry().getOperationalInfo(entityKey).getAuthorizedName();
		authorizedNameMap.put(entityKey, name);
		return name;
	}
	
	public OperationalInfo[] getOperationalInfo(String[] entityKeys) {
		return UDDIClient.getClient().getInquiry().getOperationalInfo(entityKeys);
	}
	
	public BusinessService getService(String serviceKey) {
		return UDDIClient.getClient().getInquiry().getService(serviceKey);
	}
	
	public BusinessService[] getServices(String[] serviceKeys) {
		return UDDIClient.getClient().getInquiry().getServices(serviceKeys);
	}
	

	
	public FindTModelQuery findTModel() {
		return new FindTModelQuery(UDDIClient.getClient().getInquiry().findTModel());
	}
	
	public TModel getTModel(String tModelKey) {
		TModel model = new TModel(UDDIClient.getClient().getInquiry().getTModel(tModelKey));
		ServiceDynamicParameters serviceDynamicParameters = dynamicParameterDAO.getByTModel(tModelKey);
		if (serviceDynamicParameters != null) {
			model.setDynamicParameter(serviceDynamicParameters);
		}
		return model;
	}
	
	public TModel[] getTModels(String[] keys) {
		TModel[] models = new TModel[keys.length];
		for (int i = 0; i < keys.length; i++) {
			models[i] = getTModel(keys[i]);
		}
		
		return models;
	}
	
	public TModel[] getTModels(String[] keys, String query) {
		List<String> list = dynamicParameterDAO.getTModels(query);
		List<TModel> modelList = new LinkedList<TModel>();
		List<String> keyList = Arrays.asList(keys);
		for (int i = 0; i < list.size(); i++) {
			if (keyList.contains(list.get(i))) {
				modelList.add(getTModel(list.get(i)));
			}
		}
		
		TModel[] models = new TModel[modelList.size()];
		return modelList.toArray(models);
	}
	
	public String getWSDL(String tModelKey) {
		TModel model = getTModel(tModelKey);
		if (model != null) {
			for (OverviewDoc overviewDoc : model.getModel().getOverviewDocArray()) {
				OverviewURL overviewURL = overviewDoc.getOverviewURL();
				if (overviewURL.getUseType().equals("wsdlInterface")) {
					
					DownloadWSDLParameter.update(tModelKey);		//update parameter
					return overviewURL.getStringValue();
				}
			}
		}
		
		return null;
	}

	public BusinessInfo[] findBusiness(String name) {
		FindBusinessQuery businessQuery = findBusiness();
		businessQuery.addQualifier(FindBusinessQuery.APPROXIMATE_MATCH);
		businessQuery.addName(name);
		
		return businessQuery.execute().getBusinessInfos();
	}
	
	public BindingTemplate[] findBinding(String serviceKey) {
		FindBindingQuery findBindingQuery = findBinding();
		findBindingQuery.addQualifier(FindServiceQuery.APPROXIMATE_MATCH);
		findBindingQuery.setServiceKey(serviceKey);
		FindBindingResult result = findBindingQuery.execute();
		return result.getTemplates();
	}
	
	public ServiceInfo[] findService(String businessKey, String name) {
		FindServiceQuery findServiceQuery = findService();
		findServiceQuery.setBusinessKey(businessKey);
		if (name != null) {
			findServiceQuery.addName(name);
		}
		findServiceQuery.addQualifier(FindServiceQuery.APPROXIMATE_MATCH);
		return findServiceQuery.execute().getServiceInfos();
	}
	
	public TModelInfo[] findTModel(String name, String query) {
		return findTModel(name, query, null);
	}
	
	public TModelInfo[] findTModel(String name, String query, String type) {
		FindTModelQuery findTModelQuery = findTModel();
		if (name != null) {
			findTModelQuery.setName(name);
		}
		if (query != null) {
			findTModelQuery.setDynamicQuery(query);
		}
		findTModelQuery.addQualifier(FindServiceQuery.APPROXIMATE_MATCH);
		if (type != null) {
			findTModelQuery.addCategory("type", type, "uddi:uddi.org:categorization:general_keywords");
		}
		return findTModelQuery.execute();
	}
	
}
